import test from 'tape'
import PromiseFileReader from 'promise-file-reader'

import readImageArrayBuffer from 'readImageArrayBuffer'
import readImageBlob from 'readImageBlob'
import readImageFile from 'readImageFile'
import readImageHTTP from 'readImageHTTP'

import IntTypes from 'IntTypes'
import PixelTypes from 'PixelTypes'

import getMatrixElement from 'getMatrixElement'

const cthead1SmallBase64DataURI = ''
const byteString = window.atob(cthead1SmallBase64DataURI.split(',')[1])
const mimeString = cthead1SmallBase64DataURI.split(',')[0].split(':')[1].split(';')[0]
const intArray = new Uint8Array(byteString.length)
for (let ii = 0; ii < byteString.length; ++ii) {
  intArray[ii] = byteString.charCodeAt(ii)
}
const cthead1SmallBlob = new window.Blob([intArray], { type: mimeString })
const cthead1SmallBlob1 = new window.Blob([intArray], { type: mimeString })
const cthead1SmallFile = new window.File([cthead1SmallBlob], 'cthead1Small.png')

const verifyImage = (t, image) => {
  t.is(image.imageType.dimension, 2, 'dimension')
  t.is(image.imageType.componentType, IntTypes.UInt8, 'componentType')
  t.is(image.imageType.pixelType, PixelTypes.Scalar, 'pixelType')
  t.is(image.imageType.components, 1, 'components')
  t.is(image.origin[0], 0.0, 'origin[0]')
  t.is(image.origin[1], 0.0, 'origin[1]')
  t.is(image.spacing[0], 1.0, 'spacing[0]')
  t.is(image.spacing[1], 1.0, 'spacing[1]')
  t.is(getMatrixElement(image.direction, 0, 0), 1.0, 'direction (0, 0)')
  t.is(getMatrixElement(image.direction, 0, 1), 0.0, 'direction (0, 1)')
  t.is(getMatrixElement(image.direction, 1, 0), 0.0, 'direction (1, 0)')
  t.is(getMatrixElement(image.direction, 1, 1), 1.0, 'direction (1, 1)')
  t.is(image.size[0], 32, 'size[0]')
  t.is(image.size[1], 32, 'size[1]')
  t.is(image.data.length, 1024, 'data.length')
  t.is(image.data[512], 12, 'data[512]')
  t.end()
}

test('readImageArrayBuffer reads an ArrayBuffer', (t) => {
  return PromiseFileReader.readAsArrayBuffer(cthead1SmallFile)
    .then(arrayBuffer => {
      return readImageArrayBuffer(null, arrayBuffer, 'cthead1Small.png')
        .then(function ({ image, webWorker }) {
          webWorker.terminate()
          verifyImage(t, image)
        })
    })
})

test('readImageBlob reads a Blob', (t) => {
  return readImageBlob(null, cthead1SmallBlob, 'cthead1Small.png')
    .then(function ({ image, webWorker }) {
      webWorker.terminate()
      verifyImage(t, image)
    })
})

test('readImageBlob reads a Blob without a file extension', (t) => {
  return readImageBlob(null, cthead1SmallBlob1, 'cthead1Small')
    .then(function ({ image, webWorker }) {
      webWorker.terminate()
      verifyImage(t, image)
    })
})

test('readImageFile reads a File', (t) => {
  return readImageFile(null, cthead1SmallFile)
    .then(function ({ image, webWorker }) {
      webWorker.terminate()
      verifyImage(t, image)
    })
})

test('readImageFile re-uses a WebWorker', (t) => {
  return readImageFile(null, cthead1SmallFile)
    .then(function ({ image, webWorker }) {
      return readImageFile(webWorker, cthead1SmallFile)
        .then(function ({ image, webWorker }) {
          webWorker.terminate()
          verifyImage(t, image)
        })
    })
})

test('readImageFile throws a catchable error for an invalid file', (t) => {
  const invalidArray = new Uint8Array([21, 4, 4, 4, 4, 9, 5, 0, 82, 42])
  const invalidBlob = new window.Blob([invalidArray])
  const invalidFile = new window.File([invalidBlob], 'invalid.file')
  return readImageFile(null, invalidFile).then(function ({ image, webWorker }) {
    webWorker.terminate()
    t.fail('should not have successfully read the image')
    t.end()
  }).catch(function (error) {
    t.pass(String(error))
    t.pass('thrown an error that was caught')
    t.end()
  })
})

test('readImageHTTP reads itk.js Image from a URL', (t) => {
  const testURL = 'base/build/ExternalData/test/Input/cthead1.json'
  return readImageHTTP(testURL)
    .then(function (image) {
      t.is(image.imageType.dimension, 2, 'dimension')
      t.is(image.imageType.componentType, IntTypes.UInt8, 'componentType')
      t.is(image.imageType.pixelType, PixelTypes.RGB, 'pixelType')
      t.is(image.imageType.components, 3, 'components')
      t.is(image.origin[0], 0.0, 'origin[0]')
      t.is(image.origin[1], 0.0, 'origin[1]')
      t.is(image.spacing[0], 1.0, 'spacing[0]')
      t.is(image.spacing[1], 1.0, 'spacing[1]')
      t.is(getMatrixElement(image.direction, 0, 0), 1.0, 'direction (0, 0)')
      t.is(getMatrixElement(image.direction, 0, 1), 0.0, 'direction (0, 1)')
      t.is(getMatrixElement(image.direction, 1, 0), 0.0, 'direction (1, 0)')
      t.is(getMatrixElement(image.direction, 1, 1), 1.0, 'direction (1, 1)')
      t.is(image.size[0], 256, 'size[0]')
      t.is(image.size[1], 256, 'size[1]')
      t.is(image.data.length, 196608, 'data.length')
      t.is(image.data[512], 10, 'data[512]')
      t.end()
    })
})
